package com.chisheng.caa.filter;

import cn.hutool.core.util.ObjectUtil;
import com.chisheng.caa.config.RedisCacheNames;
import com.chisheng.caa.pojo.response.JsonResponse;
import com.chisheng.caa.pojo.LoginUserDetails;
import com.chisheng.caa.util.JwtUtil;
import com.chisheng.caa.util.RedisCacheUtil;
import com.chisheng.caa.util.WebUtil;
import lombok.NonNull;
import lombok.SneakyThrows;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * JWT 认证过滤器
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Resource
    private RedisCacheUtil redisCacheUtil;

    @Override
    @SneakyThrows
    protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) {
        // 从请求头中获取 TOKEN
        String token = request.getHeader(JwtUtil.TOKEN_HEADER);
        if (ObjectUtil.isEmpty(token)) {
            // 无 TOKEN 则放行，交给后续处理器处理
            filterChain.doFilter(request, response);
            return;
        }

        // 解析 TOKEN
        Object userId = JwtUtil.parseToken(token);
        if (ObjectUtil.isEmpty(userId)) {
            // 不携带 TOKEN
            WebUtil.renderJson(response, JsonResponse.failure("无效参数"));
            return;
        }

        // 从缓存中获取用户信息
        String cacheKey = RedisCacheNames.OAUTH_PREFIX + userId;
        LoginUserDetails user = redisCacheUtil.getCacheObject(cacheKey);
        if (ObjectUtil.isEmpty(user)) {
            // 携带 TOKEN 但 Redis 缓存无效
            WebUtil.renderJson(response, JsonResponse.failure("账户登录过期，请重新登录"));
            return;
        }

        // 存入 SecurityContextHolder 中
        Authentication auth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(auth);
        filterChain.doFilter(request, response);
    }

}
